'use client'

import React, { useEffect, useState, useCallback } from 'react'
import { useParams, useRouter } from 'next/navigation'
import { useSession } from 'next-auth/react'
import Button from '@/components/ui/Button'
import Link from 'next/link'
import { toast } from 'react-hot-toast'
import { ArrowLeftIcon, ArrowRightIcon, CheckCircleIcon, InformationCircleIcon } from '@heroicons/react/24/outline'
import CodeEditorComponent from '@/components/ui/CodeEditor'

interface StageContent {
  question?: string;
  options?: { id: string; text: string }[];
  correctAnswer?: string | string[]; 
  maxScore?: number;
  instructions?: string;
  answerExplanation?: string;
  language?: string;
  languageVersion?: string;
}

interface ExperimentStageData {
  id: string;
  title: string;
  description: string;
  order: number;
  type: string; 
  content: StageContent & {
    prompt?: string;
    template?: string;
    testCases?: any[];
    allowedFileTypes?: string;
    maxFileSizeMB?: number;
    options?: Array<{ id: string; text: string }>;
    correctAnswerId?: string | null;
    standardAnswers?: string[];
    matchCase?: boolean;
    points?: number;
  }; 
  experimentId: string;
  experiment: {
    title: string;
    startTime: string;
    endTime: string;
    allowLateSubmission: boolean;
    stages: { id: string; order: number; title: string }[];
  };
}

interface StageSubmissionAnswer {
  selectedOption?: string; 
  selectedOptions?: string[];
  textInput?: string; 
  fileUrl?: string; 
  fileName?: string;
  code?: string;
}

interface StageSubmission {
  id: string;
  answer: StageSubmissionAnswer | null;
  score: number | null;
  submittedAt?: string | null;
}

interface FileUploadContent {
  prompt?: string;
  allowedFileTypes?: string;
  maxFileSizeMB?: number;
  points?: number;
}

export default function ExperimentStagePage() {
  const params = useParams();
  const router = useRouter();
  const { data: session, status: sessionStatus } = useSession();

  const experimentId = params.id as string;
  const stageId = params.stageId as string;

  const [stageData, setStageData] = useState<ExperimentStageData | null>(null);
  const [submission, setSubmission] = useState<StageSubmission | null>(null);
  const [experimentSubmissionStatus, setExperimentSubmissionStatus] = useState<string | null>(null);
  const [currentAnswer, setCurrentAnswer] = useState<StageSubmissionAnswer>({});
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [isSubmittingExperiment, setIsSubmittingExperiment] = useState(false);
  const [fileToUpload, setFileToUpload] = useState<File | null>(null);
  const [isEvaluating, setIsEvaluating] = useState(false);
  const [evaluationResults, setEvaluationResults] = useState<Array<any> | null>(null);

  const [teacherDefinedLanguage, setTeacherDefinedLanguage] = useState<string | undefined>(undefined);
  const [teacherDefinedLanguageVersion, setTeacherDefinedLanguageVersion] = useState<string | undefined>(undefined);

  const fetchStageDetails = useCallback(async () => {
    if (!experimentId || !stageId || sessionStatus !== 'authenticated') return;
    setLoading(true);
    setError(null);
    try {
      const response = await fetch(`/api/experiments/${experimentId}/stages/${stageId}`);
      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(errorData.message || `获取阶段详情失败 (${response.status})`);
      }
      const data = await response.json();
      setStageData(data.stage);
      setSubmission(data.submission || null);
      setExperimentSubmissionStatus(data.experimentSubmissionStatus || 'IN_PROGRESS');
      
      let initialAnswer: StageSubmissionAnswer = {};
      if (data.submission?.answer) {
        initialAnswer = data.submission.answer;
        setCurrentAnswer(initialAnswer);
      } else {
        setCurrentAnswer({});
      }

      if (data.stage?.type === 'CODE') {
        const content = data.stage.content as ExperimentStageData['content'];
        setTeacherDefinedLanguage(content.language);
        setTeacherDefinedLanguageVersion(content.languageVersion);
        
        if (!initialAnswer.code && content.template) {
          setCurrentAnswer(prev => ({ ...prev, code: content.template }));
        }
      }

    } catch (err: any) {
      console.error('获取阶段详情错误:', err);
      setError(err.message);
      toast.error(err.message || '获取阶段详情失败');
    }
    setLoading(false);
  }, [experimentId, stageId, sessionStatus]);

  useEffect(() => {
    if (sessionStatus === 'loading') return;
    if (sessionStatus === 'unauthenticated') {
      router.replace('/login');
      return;
    }
  }, [sessionStatus, router]);

  useEffect(() => {
    if (sessionStatus === 'authenticated' && stageId) {
        setCurrentAnswer({}); 
        setFileToUpload(null); 
        setTeacherDefinedLanguage(undefined);
        setTeacherDefinedLanguageVersion(undefined);
        setEvaluationResults(null);
        fetchStageDetails();
    }
  }, [stageId, sessionStatus, fetchStageDetails]);

  const handleAnswerChange = (answerPart: Partial<StageSubmissionAnswer>) => {
    if (experimentSubmissionStatus === 'SUBMITTED' || experimentSubmissionStatus === 'GRADED') {
        toast.error('实验已提交或已评分，无法修改答案。');
        return;
    }
    setCurrentAnswer(prev => ({ ...prev, ...answerPart }));
  };

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (experimentSubmissionStatus === 'SUBMITTED' || experimentSubmissionStatus === 'GRADED') {
        toast.error('实验已提交或已评分，无法上传文件。');
        if(event.target.value) event.target.value = '';
        return;
    }
    if (event.target.files && event.target.files[0]) {
      setFileToUpload(event.target.files[0]);
    }
  };

  const handleSaveAnswer = async (evaluate = false) => {
    if (!stageData) {
        toast.error('无法加载阶段数据，无法保存。');
        return;
    }
    const isExperimentOver = stageData.experiment.endTime && new Date() > new Date(stageData.experiment.endTime);
    const canStillSave = !isExperimentOver || (stageData.experiment.allowLateSubmission ?? false);
    if (!canStillSave && session?.user.role === 'STUDENT' && !evaluate) {
        toast.error('实验已结束，无法再保存答案。');
        return;
    }

    if (evaluate) {
      setIsEvaluating(true);
      toast.loading('正在运行测试...', { id: 'evalTestToast' });
      setEvaluationResults(null);
    } else {
    setIsSaving(true);
      toast.loading('正在保存答案...', { id: 'saveAnswerToast' });
    }
    

    let answerToSave: StageSubmissionAnswer & { language?: string; languageVersion?: string } = { ...currentAnswer };

    if (stageData.type === 'CODE') {
      if (!teacherDefinedLanguage || !teacherDefinedLanguageVersion) {
        const message = '代码语言或版本未配置，无法保存或评测。请联系教师。';
        toast.error(message, { id: evaluate ? 'evalTestToast' : 'saveAnswerToast' });
        if (evaluate) setIsEvaluating(false); else setIsSaving(false);
        return;
      }
      answerToSave.language = teacherDefinedLanguage;
      answerToSave.languageVersion = teacherDefinedLanguageVersion;
    }

    if (stageData.type === 'FILE_UPLOAD' && fileToUpload && !evaluate) {
        const formDataBody = new FormData();
        formDataBody.append('file', fileToUpload);
        formDataBody.append('experimentId', experimentId);
        formDataBody.append('stageId', stageId);

        try {
            const uploadResponse = await fetch('/api/upload', {
                method: 'POST',
                body: formDataBody,
            });
            if (!uploadResponse.ok) {
                const errorData = await uploadResponse.json().catch(() => ({}));
                throw new Error(errorData.message || '文件上传失败');
            }
            const uploadedFileData = await uploadResponse.json();
            answerToSave.fileUrl = uploadedFileData.fileUrl;
            answerToSave.fileName = fileToUpload.name;
            setFileToUpload(null); 
        } catch (err: any) {
            toast.error(err.message || '文件上传处理失败', { id: 'saveAnswerToast' });
            setIsSaving(false);
            return;
        }
    }

    try {
      const response = await fetch(`/api/experiments/${experimentId}/stages/${stageId}/answer`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ 
          answer: answerToSave,
          evaluate: evaluate
        }),
      });
      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(errorData.message || (evaluate ? '运行测试失败' : '保存答案失败'));
      }
      const data = await response.json();

      if (evaluate) {
        setEvaluationResults(data.evaluationResults || []);
        toast.success('测试运行完成!', { id: 'evalTestToast' });
        if (data.submission) {
            setSubmission(data.submission);
        }
      } else {
      setSubmission(data.submission);
        toast.success('答案已保存', { id: 'saveAnswerToast' });
      }
    } catch (err: any) {
      console.error(evaluate ? '运行测试错误:' : '保存答案错误:', err);
      toast.error(err.message || (evaluate ? '运行测试失败' : '保存答案失败'), { id: evaluate ? 'evalTestToast' : 'saveAnswerToast' });
    }
    if (evaluate) setIsEvaluating(false); else setIsSaving(false);
  };  

  const handleRunTests = () => {
    if (!stageData || stageData.type !== 'CODE') {
      toast.error('此阶段不支持运行测试。');
        return;
    }
    if (!currentAnswer.code?.trim()) {
        toast.error('请输入代码后再运行测试。');
                 return;
            }
    handleSaveAnswer(true);
  };

  const handleSubmitExperiment = async () => {
    if (isSubmittingExperiment) return;
    setIsSubmittingExperiment(true);
    toast.loading('正在提交实验...', { id: 'submitExperimentToast' });

    try {
        const response = await fetch(`/api/experiments/${experimentId}/submit`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        });

        if (!response.ok) {
            const errorData = await response.json().catch(() => ({}));
            throw new Error(errorData.message || '提交实验失败');
        }

      const result = await response.json();
      setExperimentSubmissionStatus('SUBMITTED');
      toast.success(result.message || '实验已成功提交！', { id: 'submitExperimentToast' });
      router.push(`/experiments/${experimentId}`);
    } catch (err: any) {
        console.error('提交实验错误:', err);
      toast.error(err.message || '提交实验失败，请重试。', { id: 'submitExperimentToast' });
    }
    setIsSubmittingExperiment(false);
  };

  const navigateToStage = (targetStageId: string) => {
    if (targetStageId) {
      router.push(`/experiments/${experimentId}/stages/${targetStageId}`);
    }
  };

  const renderNavigationButtons = () => {
    if (!stageData?.experiment?.stages) return null;
    const stages = stageData.experiment.stages.sort((a, b) => a.order - b.order);
    const currentIndex = stages.findIndex(s => s.id === stageId);
    const prevStage = currentIndex > 0 ? stages[currentIndex - 1] : null;
    const nextStage = currentIndex < stages.length - 1 ? stages[currentIndex + 1] : null;

    return (
      <div className="mt-8 flex justify-between items-center">
        <div>
          {prevStage && (
            <Button 
              variant="outline" 
              onClick={() => navigateToStage(prevStage.id)}
              disabled={isSaving || isEvaluating}
            >
              <ArrowLeftIcon className="h-5 w-5 mr-2" />
              上一阶段: {prevStage.title}
            </Button>
          )}
        </div>
        <div>
          {nextStage && (
            <Button 
              variant="outline" 
              onClick={() => navigateToStage(nextStage.id)}
              disabled={isSaving || isEvaluating}
            >
              下一阶段: {nextStage.title}
              <ArrowRightIcon className="h-5 w-5 ml-2" />
            </Button>
          )}
        </div>
      </div>
    );
  };

  if (loading && !stageData) {
    return <div className="container mx-auto px-4 py-8 text-center">加载中...</div>;
  }

  if (error) {
    return <div className="container mx-auto px-4 py-8 text-center text-red-500">错误: {error}</div>;
  }

  if (!stageData) {
    return <div className="container mx-auto px-4 py-8 text-center">未找到实验阶段。</div>;
  }
  
  const isExperimentOver = stageData.experiment.endTime && new Date() > new Date(stageData.experiment.endTime);
  const canEditAnswer = !(experimentSubmissionStatus === 'SUBMITTED' || experimentSubmissionStatus === 'GRADED') &&
                        (!isExperimentOver || (stageData.experiment.allowLateSubmission ?? false) || session?.user.role !== 'STUDENT');

  return (
    <div className="container mx-auto px-4 py-8">
      <div className="bg-white shadow-lg rounded-lg p-6 md:p-8">
        <div className="mb-6 pb-4 border-b border-gray-200">
          <Link href={`/experiments/${experimentId}`} className="text-sm text-primary-600 hover:underline mb-2 inline-block">
            &larr; 返回实验: {stageData.experiment.title}
        </Link>
          <h1 className="text-2xl md:text-3xl font-bold text-gray-800">{stageData.title}</h1>
          {stageData.description && <p className="text-gray-600 mt-2">{stageData.description}</p>}
        </div>

        {stageData.type === 'CODE' && teacherDefinedLanguage && (
          <div className="mb-4 p-3 bg-blue-50 border border-blue-200 rounded-md text-sm text-blue-700 flex items-center">
            <InformationCircleIcon className="h-5 w-5 mr-2 text-blue-500" />
            <span>
              编程语言: <strong>{teacherDefinedLanguage}</strong>
              {teacherDefinedLanguageVersion && ` (版本: ${teacherDefinedLanguageVersion})`}
            </span>
            </div>
        )}

        {stageData.type === 'MULTIPLE_CHOICE' && stageData.content.options && (
          <div className="space-y-3">
            <p className="text-gray-700 mb-3">{stageData.content.question || '请选择一个选项：'}</p>
            {stageData.content.options.map(option => (
              <label key={option.id} className="flex items-center p-3 border rounded-md hover:bg-gray-50 cursor-pointer">
                  <input 
                    type="radio" 
                  name="mcOption"
                    value={option.id}
                    checked={currentAnswer.selectedOption === option.id}
                    onChange={() => handleAnswerChange({ selectedOption: option.id })}
                  disabled={!canEditAnswer}
                  className="h-4 w-4 text-primary-600 border-gray-300 focus:ring-primary-500"
                  />
                  <span className="ml-3 text-gray-800">{option.text}</span>
                </label>
            ))}
          </div>
        )}

        {stageData.type === 'FILL_IN_BLANK' && (
          <div>
            <p className="text-gray-700 mb-2">{stageData.content.question || '请填写答案：'}</p>
            <input
              type="text"
              value={currentAnswer.textInput || ''}
              onChange={(e) => handleAnswerChange({ textInput: e.target.value })}
              disabled={!canEditAnswer}
              className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm"
              placeholder="在此输入您的答案"
            />
          </div>
        )}
        
        {stageData.type === 'FILE_UPLOAD' && (
          <div>
            <p className="text-gray-700 mb-2">{stageData.content.prompt || '请上传文件：'}</p>
                <input 
                type="file"
                onChange={handleFileChange}
              disabled={!canEditAnswer || isSaving}
                className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-primary-50 file:text-primary-700 hover:file:bg-primary-100"
              accept={(stageData.content as FileUploadContent).allowedFileTypes || undefined}
                />
            {fileToUpload && <p className="text-sm text-gray-600 mt-2">已选择文件: {fileToUpload.name}</p>}
            {currentAnswer.fileName && !fileToUpload && (
                <p className="text-sm text-green-600 mt-2">
                    当前已保存文件: {currentAnswer.fileName}
                    {currentAnswer.fileUrl && (
                        <a href={currentAnswer.fileUrl} target="_blank" rel="noopener noreferrer" className="ml-2 text-primary-600 hover:underline">(查看/下载)</a>
                    )}
                </p>
            )}
            {(stageData.content as FileUploadContent).maxFileSizeMB && (
              <p className="text-xs text-gray-500 mt-1">
                最大文件大小: {(stageData.content as FileUploadContent).maxFileSizeMB}MB.
              </p>
            )}
          </div>
        )}

        {stageData.type === 'CODE' && (
          <div className="space-y-4">
            <p className="text-gray-700">{stageData.content.prompt || '请编写代码：'}</p>
            <CodeEditorComponent
              language={teacherDefinedLanguage || 'plaintext'}
              value={currentAnswer.code || ''}
              onChange={(newCode) => handleAnswerChange({ code: newCode })}
              readOnly={!canEditAnswer}
              height="400px"
              theme="vs-light"
            />
            <div className="flex space-x-3">
            <Button 
                    onClick={handleRunTests} 
                    disabled={!canEditAnswer || isSaving || isEvaluating || !currentAnswer.code?.trim()}
                variant="secondary"
            >
                    {isEvaluating ? '运行中...' : '运行测试'}
            </Button>
            </div>

            {evaluationResults && evaluationResults.length > 0 && (
              <div className="mt-6">
                <h3 className="text-lg font-semibold mb-2">即时评测结果:</h3>
                <div className="space-y-3">
                  {evaluationResults.map((result, index) => (
                    <div key={index} className={`p-3 border rounded-md ${result.isCorrect ? 'border-green-300 bg-green-50' : 'border-red-300 bg-red-50'}`}>
                      <div className="flex justify-between items-center">
                        <p className="font-medium">
                          测试用例 {index + 1}: {result.testCaseName || (result.testCase?.name)} - 
                          <span className={result.isCorrect ? 'text-green-600' : 'text-red-600'}>
                            {result.status}
                          </span>
                        </p>
                        <p className="text-sm">{result.pointsAwarded ?? 0} / {result.testCase?.points ?? 'N/A'} 分</p>
                      </div>
                      {!result.isCorrect && result.runtimeError && (
                        <p className="text-xs text-red-700 mt-1">错误: {result.runtimeError}</p>
            )}
                      {result.actualOutput && (
                        <details className="mt-1 text-xs">
                          <summary className="cursor-pointer text-gray-600">查看输出</summary>
                          <pre className="mt-1 p-2 bg-gray-100 rounded text-gray-800 whitespace-pre-wrap break-all"><code>{result.actualOutput}</code></pre>
                        </details>
                      )}
                       {result.executionTimeMs !== undefined && (
                        <p className="text-xs text-gray-500 mt-1">执行时间: {result.executionTimeMs} ms</p>
                      )}
                      {result.memoryUsageKb !== undefined && (
                        <p className="text-xs text-gray-500">内存占用: {result.memoryUsageKb} KB</p>
                      )}
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}

        <div className="mt-8 pt-6 border-t border-gray-200 flex flex-col sm:flex-row justify-between items-center space-y-4 sm:space-y-0">
          <Button 
            onClick={() => handleSaveAnswer(false)}
            disabled={!canEditAnswer || isSaving || isEvaluating}
            className="w-full sm:w-auto"
          >
            {isSaving ? '保存中...' : '保存答案'}
          </Button>
          
          {stageData.experiment.stages.findIndex(s => s.id === stageId) === stageData.experiment.stages.length - 1 && (
            (experimentSubmissionStatus === null || experimentSubmissionStatus === 'IN_PROGRESS') ? (
            <Button 
                onClick={handleSubmitExperiment}
                    disabled={isSaving || isSubmittingExperiment || isEvaluating}
                variant="primary"
                className="w-full sm:w-auto"
            >
                {isSubmittingExperiment ? '提交中...' : '完成并提交整个实验'}
            </Button>
            ) : (
                <div className="text-center sm:text-right w-full sm:w-auto">
                    <p className="text-green-600 font-semibold flex items-center justify-center sm:justify-end">
                        <CheckCircleIcon className="h-5 w-5 mr-2"/>
                        实验已提交
                    </p>
                    <Link href={`/experiments/${experimentId}/history`} className="text-sm text-primary-600 hover:underline">
                        查看我的提交记录
                    </Link>
          </div>
            )
      )}
        </div>

        {renderNavigationButtons()}

      </div>
    </div>
  );
} 